//
// Created by sunhongda on 2017/06/16
//
#ifndef WIN32
#include "com_chuangmi_decoder_ImiVideoDecoder.h"
#include "imicodecffmpegapi.h"
#include "log.h"
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    nativeInit
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_nativeInit
  (JNIEnv *pJNIEnv, jclass clazz, jintArray pIMIHandle)
{
	jboolean b;
	jint* handle = pJNIEnv->GetIntArrayElements(pIMIHandle, &b);
	IMICodecFFmpeg_Init((IMICodecFFmpegHandle*)handle);
  pJNIEnv->ReleaseIntArrayElements(pIMIHandle, handle, 0);
}

/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    selectDecoder
 * Signature: (Lcom/chuangmi/decoder/ImiVideoDecoder/VideoType;I)V
 */
JNIEXPORT void JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_selectDecoder
  (JNIEnv *pJNIEnv, jobject object, jintArray pIMIHandle, jint iType, jint iFlag)
{
  jboolean b;
	jint* handle = pJNIEnv->GetIntArrayElements(pIMIHandle, &b);
	IMICodecFFmpeg_SelectDecoder((IMICodecFFmpegHandle)*handle, iType, iFlag);
  pJNIEnv->ReleaseIntArrayElements(pIMIHandle, handle, 0);
}

/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    release
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_release
  (JNIEnv *pJNIEnv, jobject object, jintArray pIMIHandle)
{
  jboolean b;
	jint* handle = pJNIEnv->GetIntArrayElements(pIMIHandle, &b);
	IMICodecFFmpeg_Fini((IMICodecFFmpegHandle)*handle);
	pJNIEnv->ReleaseIntArrayElements(pIMIHandle, handle, 0);
}

/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    decode
 * Signature: ([BIJ)Z
 */
JNIEXPORT jboolean JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_decode
  (JNIEnv *pJNIEnv, jobject object, jintArray pIMIHandle, jbyteArray pData, jint iDataLen, jlong ulPTS)
{
	jboolean b;
  jint* handle = pJNIEnv->GetIntArrayElements(pIMIHandle, &b);
	jbyte* data = pJNIEnv->GetByteArrayElements(pData, &b);
	int len = (int)iDataLen;
	int r = IMICodecFFmpeg_Decode((IMICodecFFmpegHandle)*handle, (unsigned char*)data, len, ulPTS);
	LOGE("IMICodecFFmpeg_Decode r = %d\n", r);
  pJNIEnv->ReleaseIntArrayElements(pIMIHandle, handle, 0);
	pJNIEnv->ReleaseByteArrayElements(pData, data, 0);
	if (r != 0)	return false;
	return true;
}

/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    getWidth
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_getWidth
  (JNIEnv *pJNIEnv, jobject object, jintArray pIMIHandle)
{
  jboolean b;
	jint* handle = pJNIEnv->GetIntArrayElements(pIMIHandle, &b);
	jint r = (jint)IMICodecFFmpeg_GetWidth((IMICodecFFmpegHandle)*handle);
  pJNIEnv->ReleaseIntArrayElements(pIMIHandle, handle, 0);
  return r;
}

/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    getHeight
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_getHeight
  (JNIEnv *pJNIEnv, jobject object, jintArray pIMIHandle)
{
  jboolean b;
	jint* handle = pJNIEnv->GetIntArrayElements(pIMIHandle, &b);
	jint r = (jint)IMICodecFFmpeg_GetHeight((IMICodecFFmpegHandle)*handle);
  pJNIEnv->ReleaseIntArrayElements(pIMIHandle, handle, 0);
  return r;
}

/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    toTexture
 * Signature: (III)I
 */
JNIEXPORT jint JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_toTexture
  (JNIEnv *pJNIEnv, jobject object, jintArray pIMIHandle, jint iY, jint iU, jint iV)
{
  jboolean b;
	jint* handle = pJNIEnv->GetIntArrayElements(pIMIHandle, &b);
	jint r = (jint)IMICodecFFmpeg_ToTexture((IMICodecFFmpegHandle)*handle, iY, iU, iV);
  pJNIEnv->ReleaseIntArrayElements(pIMIHandle, handle, 0);
  return r;
}

/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    getYuvData
 * Signature: ([B[B[B)I
 */
JNIEXPORT jint JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_getYuvData
  (JNIEnv *pJNIEnv, jobject object, jintArray pIMIHandle, jobject pY, jobject pU, jobject pV)
{
  jboolean b;
	jint* handle = pJNIEnv->GetIntArrayElements(pIMIHandle, &b);
	unsigned char* buffery = (unsigned char*)pJNIEnv->GetDirectBufferAddress(pY);
	unsigned char* bufferu = (unsigned char*)pJNIEnv->GetDirectBufferAddress(pU);
	unsigned char* bufferv = (unsigned char*)pJNIEnv->GetDirectBufferAddress(pV);
	int r = IMICodecFFmpeg_GetYUVData((IMICodecFFmpegHandle)*handle, buffery, bufferu, bufferv);
  pJNIEnv->ReleaseIntArrayElements(pIMIHandle, handle, 0);
	return (jint)r;
}

/*
 * Class:     com_chuangmi_decoder_ImiVideoDecoder
 * Method:    getYuvDatas
 * Signature: ([B[B[B)I
 */
JNIEXPORT jint JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_getJpegBuffer
  (JNIEnv *pJNIEnv, jobject object, jobject pY, jobject pU, jobject pV, jobject pBuffer, jint width, jint height, jint quality)
{

	return -1;
}

JNIEXPORT int JNICALL Java_com_chuangmi_decoder_ImiVideoDecoder_yuv420p2yuv420sp
(JNIEnv *pJNIEnv, jobject object, jbyteArray java_yuv420p, jbyteArray java_yuv420sp, jint width, jint height)
{
    unsigned char * yuv420p =(unsigned char *) pJNIEnv-> GetByteArrayElements(java_yuv420p,0);
    if(yuv420p == NULL){
        LOGE("yuv420p is null");
        return -1;
    }
    unsigned char * yuv420sp =(unsigned char *) pJNIEnv-> GetByteArrayElements(java_yuv420sp,0);
    if(yuv420sp == NULL){
        LOGE("yuv420sp is null");
        return -1;
    }
    int i, j;
    int y_size = width * height;

    unsigned char* y = yuv420p;
    unsigned char* u = yuv420p + y_size;
    unsigned char* v = yuv420p + y_size * 5 / 4;

    unsigned char* y_tmp = yuv420sp;
    unsigned char* uv_tmp = yuv420sp + y_size;

    // y
    memcpy(y_tmp, y, y_size);
    // u
    for (j = 0, i = 0; j < y_size/2; j+=2, i++)
    {
        uv_tmp[j] = v[i];
        uv_tmp[j+1] = u[i];
    }
    //释放资源
    pJNIEnv->ReleaseByteArrayElements(java_yuv420p,(jbyte* )yuv420p,0);
    pJNIEnv->ReleaseByteArrayElements(java_yuv420sp,(jbyte* )yuv420sp,0);
    return 0;
}

#ifdef __cplusplus
}
#endif
#endif
